﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using l1cs.server.templates;
using l1cs.server.model.Instance;
using l1cs.server.serverpackets;
using l1cs.server.datatables;

namespace l1cs.server.model
{
    public class L1War
    {
        private String _param1 = null;
        private String _param2 = null;
        private List<String> _attackClanList = new List<String>();
        private String _defenceClanName = null;
        private int _warType = 0;
        private int _castleId = 0;
        private L1Castle _castle = null;
        private DateTime _warEndTime;

        private bool _isWarTimerDelete = false;

        private static Logger _log = Logger.getLogger( typeof( L1War ).FullName );

        public L1War()
        {
        }

        //class CastleWarTimer
        //{
        //    public CastleWarTimer()
        //    {
        //    }

        public void CastleWarTimerSub( object state )
        {
            for ( ; ; )
            {
                Thread.Sleep( 1000 );
                if ( _warEndTime < DateTime.Now )
                {
                    break;
                }
                if ( _isWarTimerDelete )
                { // 戦争が終結していたらタイマー終了
                    return;
                }
            }
            CeaseCastleWar(); // 攻城戦終結処理
            delete();
        }
        //}

        //class SimWarTimer
        //{
        //    public SimWarTimer()
        //    {
        //    }

        public void SimWarTimerSub( object state )
        {
            for ( int loop = 0; loop < 240; loop++ )
            {
                // 240分
                Thread.Sleep( 60000 );
                if ( _isWarTimerDelete )
                { // 戦争が終結していたらタイマー終了
                    return;
                }
            }
            CeaseWar( _param1, _param2 ); // 終結
            delete();
        }
        //}

        public void handleCommands( int war_type, String attack_clan_name, String defence_clan_name )
        {
            // war_type - 1:攻城戦 2:模擬戦
            // attack_clan_name - 布告したクラン名
            // defence_clan_name - 布告されたクラン名（攻城戦時は、城主クラン）

            SetWarType( war_type );

            DeclareWar( attack_clan_name, defence_clan_name );

            _param1 = attack_clan_name;
            _param2 = defence_clan_name;
            InitAttackClan();
            AddAttackClan( attack_clan_name );
            SetDefenceClanName( defence_clan_name );

            if ( war_type == 1 )
            { // 攻城戦
                _castleId = GetCastleId();
                _castle = GetCastle();
                if ( _castle != null )
                {
                    DateTime cal = _castle.getWarTime();
                    //cal.add( Config.ALT_WAR_TIME_UNIT, Config.ALT_WAR_TIME );
                    if ( Config.ALT_WAR_TIME_UNIT == "d" )
                        cal.AddDays( Config.ALT_WAR_TIME );
                    else if ( Config.ALT_WAR_TIME_UNIT == "h" )
                        cal.AddHours( Config.ALT_WAR_TIME );
                    else if ( Config.ALT_WAR_TIME_UNIT == "m" )
                        cal.AddMinutes( Config.ALT_WAR_TIME );
                    _warEndTime = cal;
                }

                //CastleWarTimer castle_war_timer = new CastleWarTimer();
                //GeneralThreadPool.getInstance().execute( castle_war_timer ); // タイマー開始
                ThreadPool.QueueUserWorkItem( new WaitCallback( CastleWarTimerSub ) );
            }
            else if ( war_type == 2 )
            { // 模擬戦
                //SimWarTimer sim_war_timer = new SimWarTimer();
                //GeneralThreadPool.getInstance().execute( sim_war_timer ); // タイマー開始
                ThreadPool.QueueUserWorkItem( new WaitCallback( SimWarTimerSub ) );
            }
            L1World.getInstance().addWar( this ); // 戦争リストに追加
        }

        private void RequestCastleWar( int type, String clan1_name, String clan2_name )
        {
            if ( clan1_name == null || clan2_name == null )
            {
                return;
            }

            L1Clan clan1 = L1World.getInstance().getClan( clan1_name );
            if ( clan1 != null )
            {
                L1PcInstance[] clan1_member = clan1.getOnlineClanMember();
                for ( int cnt = 0; cnt < clan1_member.Length; cnt++ )
                {
                    clan1_member[cnt].sendPackets( new S_War( type, clan1_name,
                            clan2_name ) );
                }
            }

            int attack_clan_num = GetAttackClanListSize();

            if ( type == 1 || type == 2 || type == 3 )
            { // 宣戦布告、降伏、終結
                L1Clan clan2 = L1World.getInstance().getClan( clan2_name );
                if ( clan2 != null )
                {
                    L1PcInstance[] clan2_member = clan2.getOnlineClanMember();
                    for ( int cnt = 0; cnt < clan2_member.Length; cnt++ )
                    {
                        if ( type == 1 )
                        { // 宣戦布告
                            clan2_member[cnt].sendPackets( new S_War( type,
                                    clan1_name, clan2_name ) );
                        }
                        else if ( type == 2 )
                        { // 降伏
                            clan2_member[cnt].sendPackets( new S_War( type,
                                    clan1_name, clan2_name ) );
                            if ( attack_clan_num == 1 )
                            { // 攻撃側クランが一つ
                                clan2_member[cnt].sendPackets( new S_War( 4,
                                        clan2_name, clan1_name ) );
                            }
                            else
                            {
                                clan2_member[cnt].sendPackets( new S_ServerMessage( // %0血盟が%1血盟に降伏しました。
                                        228, clan1_name, clan2_name ) );
                                RemoveAttackClan( clan1_name );
                            }
                        }
                        else if ( type == 3 )
                        { // 終結
                            clan2_member[cnt].sendPackets( new S_War( type,
                                    clan1_name, clan2_name ) );
                            if ( attack_clan_num == 1 )
                            { // 攻撃側クランが一つ
                                clan2_member[cnt].sendPackets( new S_War( 4,
                                        clan2_name, clan1_name ) );
                            }
                            else
                            {
                                clan2_member[cnt].sendPackets( new S_ServerMessage( // %0血盟と%1血盟間の戦争が終結しました。
                                        227, clan1_name, clan2_name ) );
                                RemoveAttackClan( clan1_name );
                            }
                        }
                    }
                }
            }

            if ( ( type == 2 || type == 3 ) && attack_clan_num == 1 )
            { // 降伏、終結で攻撃側クランが一つ
                _isWarTimerDelete = true;
                delete();
            }
        }

        private void RequestSimWar( int type, String clan1_name, String clan2_name )
        {
            if ( clan1_name == null || clan2_name == null )
            {
                return;
            }

            L1Clan clan1 = L1World.getInstance().getClan( clan1_name );
            if ( clan1 != null )
            {
                L1PcInstance[] clan1_member = clan1.getOnlineClanMember();
                for ( int cnt = 0; cnt < clan1_member.Length; cnt++ )
                {
                    clan1_member[cnt].sendPackets( new S_War( type, clan1_name,
                            clan2_name ) );
                }
            }

            if ( type == 1 || type == 2 || type == 3 )
            { // 宣戦布告、降伏、終結
                L1Clan clan2 = L1World.getInstance().getClan( clan2_name );
                if ( clan2 != null )
                {
                    L1PcInstance[] clan2_member = clan2.getOnlineClanMember();
                    for ( int cnt = 0; cnt < clan2_member.Length; cnt++ )
                    {
                        if ( type == 1 )
                        { // 宣戦布告
                            clan2_member[cnt].sendPackets( new S_War( type,
                                    clan1_name, clan2_name ) );
                        }
                        else if ( type == 2 || type == 3 )
                        { // 降伏、終結
                            clan2_member[cnt].sendPackets( new S_War( type,
                                    clan1_name, clan2_name ) );
                            clan2_member[cnt].sendPackets( new S_War( 4, clan2_name,
                                    clan1_name ) );
                        }
                    }
                }
            }

            if ( type == 2 || type == 3 )
            { // 降伏、終結
                _isWarTimerDelete = true;
                delete();
            }
        }

        public void WinCastleWar( String clan_name )
        { // クラウンを奪取して、攻撃側クランが勝利
            String defence_clan_name = GetDefenceClanName();
            L1World.getInstance().broadcastPacketToAll( new S_ServerMessage( // %0血盟が%1血盟との戦争で勝利しました。
                    231, clan_name, defence_clan_name ) );

            L1Clan defence_clan = L1World.getInstance().getClan( defence_clan_name );
            if ( defence_clan != null )
            {
                L1PcInstance[] defence_clan_member = defence_clan
                        .getOnlineClanMember();
                for ( int i = 0; i < defence_clan_member.Length; i++ )
                {
                    foreach ( String clanName in GetAttackClanList() )
                    {
                        defence_clan_member[i].sendPackets( new S_War( 3,
                                defence_clan_name, clanName ) );
                    }
                }
            }

            String[] clanList = GetAttackClanList();
            for ( int j = 0; j < clanList.Length; j++ )
            {
                if ( clanList[j] != null )
                {
                    L1World.getInstance().broadcastPacketToAll( new S_ServerMessage( // %0血盟と%1血盟間の戦争が終結しました。
                            227, defence_clan_name, clanList[j] ) );
                    L1Clan clan = L1World.getInstance().getClan( clanList[j] );
                    if ( clan != null )
                    {
                        L1PcInstance[] clan_member = clan.getOnlineClanMember();
                        for ( int k = 0; k < clan_member.Length; k++ )
                        {
                            clan_member[k].sendPackets( new S_War( 3, clanList[j],
                                    defence_clan_name ) );
                        }
                    }
                }
            }

            _isWarTimerDelete = true;
            delete();
        }

        public void CeaseCastleWar()
        { // 戦争時間満了し、防衛側クランが勝利
            String defence_clan_name = GetDefenceClanName();
            String[] clanList = GetAttackClanList();
            if ( defence_clan_name != null )
            {
                L1World.getInstance().broadcastPacketToAll( new S_ServerMessage( // %0血盟が%1血盟との戦争で勝利しました。
                        231, defence_clan_name, clanList[0] ) );
            }

            L1Clan defence_clan = L1World.getInstance().getClan( defence_clan_name );
            if ( defence_clan != null )
            {
                L1PcInstance[] defence_clan_member = defence_clan
                        .getOnlineClanMember();
                for ( int i = 0; i < defence_clan_member.Length; i++ )
                {
                    defence_clan_member[i].sendPackets( new S_War( 4,
                            defence_clan_name, clanList[0] ) );
                }
            }

            for ( int j = 0; j < clanList.Length; j++ )
            {
                if ( clanList[j] != null )
                {
                    L1World.getInstance().broadcastPacketToAll( new S_ServerMessage( // %0血盟と%1血盟間の戦争が終結しました。
                            227, defence_clan_name, clanList[j] ) );
                    L1Clan clan = L1World.getInstance().getClan( clanList[j] );
                    if ( clan != null )
                    {
                        L1PcInstance[] clan_member = clan.getOnlineClanMember();
                        for ( int k = 0; k < clan_member.Length; k++ )
                        {
                            clan_member[k].sendPackets( new S_War( 3, clanList[j],
                                    defence_clan_name ) );
                        }
                    }
                }
            }

            _isWarTimerDelete = true;
            delete();
        }

        public void DeclareWar( String clan1_name, String clan2_name )
        {
            // _血盟が_血盟に宣戦布告しました。
            if ( GetWarType() == 1 )
            { // 攻城戦
                RequestCastleWar( 1, clan1_name, clan2_name );
            }
            else
            { // 模擬戦
                RequestSimWar( 1, clan1_name, clan2_name );
            }
        }

        public void SurrenderWar( String clan1_name, String clan2_name )
        {
            // _血盟が_血盟に降伏しました。
            if ( GetWarType() == 1 )
            {
                RequestCastleWar( 2, clan1_name, clan2_name );
            }
            else
            {
                RequestSimWar( 2, clan1_name, clan2_name );
            }
        }

        public void CeaseWar( String clan1_name, String clan2_name )
        {
            // _血盟と_血盟との戦争が終結しました。
            if ( GetWarType() == 1 )
            {
                RequestCastleWar( 3, clan1_name, clan2_name );
            }
            else
            {
                RequestSimWar( 3, clan1_name, clan2_name );
            }
        }

        public void WinWar( String clan1_name, String clan2_name )
        {
            // _血盟が_血盟との戦争で勝利しました。
            if ( GetWarType() == 1 )
            {
                RequestCastleWar( 4, clan1_name, clan2_name );
            }
            else
            {
                RequestSimWar( 4, clan1_name, clan2_name );
            }
        }

        public bool CheckClanInWar( String clan_name )
        {
            // クランが戦争に参加しているかチェックする
            bool ret;
            if ( string.Compare( GetDefenceClanName(), clan_name, true ) == 0 )
            { // 防衛側クランをチェック
                ret = true;
            }
            else
            {
                ret = CheckAttackClan( clan_name ); // 攻撃側クランをチェック
            }
            return ret;
        }

        public bool CheckClanInSameWar( String player_clan_name, String target_clan_name )
        {
            // 自クランと相手クランが同じ戦争に参加しているかチェックする（同じクランの場合も含む）
            bool player_clan_flag;
            bool target_clan_flag;

            if ( string.Compare( GetDefenceClanName(), player_clan_name, true ) == 0 )
            { // 自クランに対して防衛側クランをチェック
                player_clan_flag = true;
            }
            else
            {
                player_clan_flag = CheckAttackClan( player_clan_name ); // 自クランに対して攻撃側クランをチェック
            }

            if ( string.Compare( GetDefenceClanName(), target_clan_name, true ) == 0 )
            {
                // 相手クランに対して防衛側クランをチェック
                target_clan_flag = true;
            }
            else
            {
                target_clan_flag = CheckAttackClan( target_clan_name ); // 相手クランに対して攻撃側クランをチェック
            }

            if ( player_clan_flag == true && target_clan_flag == true )
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public String GetEnemyClanName( String player_clan_name )
        {
            // 相手のクラン名を取得する
            String enemy_clan_name = null;
            if ( string.Compare( GetDefenceClanName(), player_clan_name, true ) == 0 )
            {
                // 自クランが防衛側
                String[] clanList = GetAttackClanList();
                for ( int cnt = 0; cnt < clanList.Length; cnt++ )
                {
                    if ( clanList[cnt] != null )
                    {
                        enemy_clan_name = clanList[cnt];
                        return enemy_clan_name; // リストの先頭のクラン名を返す
                    }
                }
            }
            else
            {
                // 自クランが攻撃側
                enemy_clan_name = GetDefenceClanName();
                return enemy_clan_name;
            }
            return enemy_clan_name;
        }

        public void delete()
        {
            L1World.getInstance().removeWar( this ); // 戦争リストから削除
        }

        public int GetWarType()
        {
            return _warType;
        }

        public void SetWarType( int war_type )
        {
            _warType = war_type;
        }

        public String GetDefenceClanName()
        {
            return _defenceClanName;
        }

        public void SetDefenceClanName( String defence_clan_name )
        {
            _defenceClanName = defence_clan_name;
        }

        public void InitAttackClan()
        {
            _attackClanList.Clear();
        }

        public void AddAttackClan( String attack_clan_name )
        {
            if ( !_attackClanList.Contains( attack_clan_name ) )
            {
                _attackClanList.Add( attack_clan_name );
            }
        }

        public void RemoveAttackClan( String attack_clan_name )
        {
            if ( _attackClanList.Contains( attack_clan_name ) )
            {
                _attackClanList.Remove( attack_clan_name );
            }
        }

        public bool CheckAttackClan( String attack_clan_name )
        {
            if ( _attackClanList.Contains( attack_clan_name ) )
            {
                return true;
            }
            return false;
        }

        public String[] GetAttackClanList()
        {
            return _attackClanList.ToArray();
        }

        public int GetAttackClanListSize()
        {
            return _attackClanList.Count;
        }

        public int GetCastleId()
        {
            int castle_id = 0;
            if ( GetWarType() == 1 )
            { // 攻城戦
                L1Clan clan = L1World.getInstance().getClan( GetDefenceClanName() );
                if ( clan != null )
                {
                    castle_id = clan.getCastleId();
                }
            }
            return castle_id;
        }

        public L1Castle GetCastle()
        {
            L1Castle l1castle = null;
            if ( GetWarType() == 1 )
            { // 攻城戦
                L1Clan clan = L1World.getInstance().getClan( GetDefenceClanName() );
                if ( clan != null )
                {
                    int castle_id = clan.getCastleId();
                    l1castle = CastleTable.getInstance().getCastleTable( castle_id );
                }
            }
            return l1castle;
        }
    }
}
